package com.chai.nfcrw;

import android.net.Uri;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.Tag;
import android.nfc.tech.Ndef;

import androidx.annotation.NonNull;

import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;

public class NFCUtils {
    /**
     * @param tag 标签
     * @return 内容
     */
    public static String readNfcTagData(Tag tag) {
        // 获取NDEF技术对象
        Ndef ndef = Ndef.get(tag);
        if (ndef != null) {
            try {
                // 连接到NDEF标签
                ndef.connect();
                // 检查NDEF消息是否存在
                NdefMessage message = ndef.getNdefMessage();
                if (message != null) {
                    return getStringBuilder(message);
                } else {
                    return "标签为空";
                }
            } catch (Exception e) {
                // 捕获并处理读取NFC标签时的异常
                e.printStackTrace();
                return "";
            } finally {
                try {
                    // 关闭NDEF连接
                    ndef.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        } else {
            // 不支持NDEF技术，需要特殊方式读取
            return "不支持的标签类型";
        }
    }


    /**
     * RTD_TEXT = {0x54};  // "T"
     * RTD_URI = {0x55};   // "U"
     * RTD_SMART_POSTER = {0x53, 0x70};  // "Sp"
     * RTD_ALTERNATIVE_CARRIER = {0x61, 0x63};  // "ac"
     * RTD_HANDOVER_CARRIER = {0x48, 0x63};  // "Hc"
     * RTD_HANDOVER_REQUEST = {0x48, 0x72};  // "Hr"
     * RTD_HANDOVER_SELECT = {0x48, 0x73}; // "Hs"
     * @param message
     * @return
     * @throws UnsupportedEncodingException
     */
    @NonNull
    private static String getStringBuilder(NdefMessage message) throws UnsupportedEncodingException {
        StringBuilder sb = new StringBuilder();
        for (NdefRecord record : message.getRecords()) {
            // 检查是否为文本记录
            if (record.getTnf() == NdefRecord.TNF_WELL_KNOWN) {
                if (Arrays.equals(record.getType(), NdefRecord.RTD_TEXT)){
                    sb.append("NdefRecord.RTD_TEXT\t");
                    if (record.getPayload().length > 1) {
                        // 解析出文本数据
                        String textRecord = parseTextRecord(record.getPayload());
                        sb.append(textRecord).append("\n");
                    }
                }else if(Arrays.equals(record.getType(), NdefRecord.RTD_URI)){
                    sb.append("NdefRecord.RTD_URI\t");
                    if (record.getPayload().length > 1) {
                        // 解析出文本数据
                        String textRecord = parseUriRecord(record.getPayload());
                        sb.append(textRecord).append("\n");
                    }
                }else if(Arrays.equals(record.getType(), NdefRecord.RTD_SMART_POSTER)){
                    sb.append("NdefRecord.RTD_SMART_POSTER\t");
                    if (record.getPayload().length > 1) {
                        // 解析出文本数据
                        String textRecord = parseSmartPoster(record.getPayload());
                        sb.append(textRecord).append("\n");
                    }
                }else if(Arrays.equals(record.getType(), NdefRecord.RTD_ALTERNATIVE_CARRIER)){
                    sb.append("NdefRecord.RTD_ALTERNATIVE_CARRIER\t");
                    if (record.getPayload().length > 1) {
                        // 解析出文本数据
                        String textRecord = parseAlternativeCarrier(record.getPayload());
                        sb.append(textRecord).append("\n");
                    }
                }
                else if(Arrays.equals(record.getType(), NdefRecord.RTD_HANDOVER_CARRIER)){
                    sb.append("NdefRecord.RTD_HANDOVER_CARRIER\t");
                    if (record.getPayload().length > 1) {
                        // 解析出文本数据
                        String textRecord = parseHandoverCarrier(record.getPayload());
                        sb.append(textRecord).append("\n");
                    }
                }
                else if(Arrays.equals(record.getType(), NdefRecord.RTD_HANDOVER_REQUEST)){
                    sb.append("NdefRecord.RTD_HANDOVER_REQUEST\t");
                    if (record.getPayload().length > 1) {
                        // 解析出文本数据
                        String textRecord = parseHandoverRequest(record.getPayload());
                        sb.append(textRecord).append("\n");
                    }
                }
                else if(Arrays.equals(record.getType(), NdefRecord.RTD_ALTERNATIVE_CARRIER)){
                    sb.append("NdefRecord.RTD_ALTERNATIVE_CARRIER\t");
                    if (record.getPayload().length > 1) {
                        // 解析出文本数据
                        String textRecord = parseAlternativeCarrier(record.getPayload());
                        sb.append(textRecord).append("\n");
                    }
                }
            }
        }
        return sb.toString();
    }

    /**
     * 解析NDEF文本数据，从第三个字节开始，后面的文本数据
     *
     * @param payload ndef数据
     * @return string 数据
     */
    public static String parseTextRecord(byte[] payload) throws UnsupportedEncodingException {
        //下面开始NDEF文本数据第一个字节，状态字节
        //判断文本是基于UTF-8还是UTF-16的，取第一个字节"位与"上16进制的80，16进制的80也就是最高位是1，
        //其他位都是0，所以进行"位与"运算后就会保留最高位
        String textEncoding = ((payload[0] & 0x80) == 0) ? "UTF-8" : "UTF-16";
        //3f最高两位是0，第六位是1，所以进行"位与"运算后获得第六位
        int languageCodeLength = payload[0] & 0x3f;
        //下面开始NDEF文本数据第二个字节，语言编码
        //获得语言编码
        String languageCode = new String(payload, 1, languageCodeLength, StandardCharsets.US_ASCII);
        //下面开始NDEF文本数据后面的字节，解析出文本
        return new String(payload, languageCodeLength + 1,
                payload.length - languageCodeLength - 1, textEncoding);
    }

    /**
     * 解析NDEF URI数据，从第二个字节开始，后面的文本数据
     * @param payload ndef数据
     * @return string 数据
     */
    private static String parseUriRecord(byte[] payload) {
        // URI记录的第一个字节表示标识码（Identifier Code），用于指定URI前缀
        // 第二个字节开始才是实际的URI数据
        int identifierCode = payload[0] & 0xFF;
        String prefix = getUriPrefix(identifierCode);
        String uriData = new String(payload, 1, payload.length - 1, StandardCharsets.US_ASCII);
        return prefix + uriData;
    }


    // 根据identifier code获取对应的URI前缀
    private static String getUriPrefix(int code) {
        switch(code) {
            case 0x00: return "";
            case 0x01: return "http://www.";
            case 0x02: return "https://www.";
            case 0x03: return "http://";
            case 0x04: return "https://";
            // 其他可能的前缀
            default: return "unknown:";
        }
    }


    /**
     * 解析Smart Poster记录
     */
    private static String parseSmartPoster(byte[] payload) {
        return parseUriRecord(payload);
    }

    /**
     * TODO
     * @param payload
     * @return
     */
    private static String parseAlternativeCarrier(byte[] payload) {
        return parseUriRecord(payload);
    }

    /**
     * TODO
     * @param payload
     * @return
     */
    private static String parseHandoverCarrier(byte[] payload) {
        return parseUriRecord(payload);
    }

    /**
     * TODO
     * @param payload
     * @return
     */
    private static String parseHandoverRequest(byte[] payload) {
        return parseUriRecord(payload);
    }


    /**
     * @param data 字符
     * @param tag  标签
     * @return 是否写入成功
     */
    public static boolean writeDataToNfcTag(String data, Tag tag) {
        NdefRecord ndefRecord = NdefRecord.createTextRecord("en", data);
        return writeToNfcTag(tag, ndefRecord);
    }

    /**
     * @param tag         标签
     * @param packageName 应用包名
     * @return 是否写入成功
     */
    public static boolean writeAppLaunchUriToNfcTag(Tag tag, String packageName) {
        NdefRecord applicationRecord = NdefRecord.createApplicationRecord(packageName);
        return writeToNfcTag(tag, applicationRecord);
    }

    /**
     * @param tag 标签
     * @param url url地址
     * @return 是否写入成功
     */
    public static boolean writeUrlToNfcTag(Tag tag, String url) {
        // 根据网址创建待写入的数据
        NdefRecord urlRecord = NdefRecord.createUri(Uri.parse(url));
        return writeToNfcTag(tag, urlRecord);
    }

    /**
     * @param tag       标签
     * @param longitude 经度
     * @param latitude  纬度
     * @param address   地址
     * @return 是否写入成功
     */
    public static boolean writeAddressToNfcTag(Tag tag, String longitude, String latitude, String address) {
        // 创建一个自定义的NdefRecord来存储经纬度信息
        String uriString = "amapuri://route/plan/?dlat=" + latitude + "&dlon=" + longitude + "&dname=" + address;
        return writeUrlToNfcTag(tag, uriString);
    }

    public static boolean writeToNfcTag(Tag tag, NdefRecord... urlRecord) {
        if (tag == null) {
            return false;
        }
        NdefMessage message = new NdefMessage(urlRecord);
        try {
            Ndef ndef = Ndef.get(tag);
            if (ndef != null) {
                ndef.connect();
                ndef.writeNdefMessage(message);
                ndef.close();
                return true;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return false;
    }
}
